using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using log4net;
using Triton.Common.LogUtilities;

namespace Triton.Common
{
	public class AssemblyLoader<T>
	{
		[CompilerGenerated]
		private sealed class Class229
		{
			public T gparam_0;

			internal bool method_0(T gparam_1)
			{
				string fullName = gparam_1.GetType().FullName;
				string fullName2 = gparam_0.GetType().FullName;
				return fullName == fullName2;
			}
		}

		private readonly ILog ilog_0 = Logger.GetLoggerInstanceForType();

		private readonly bool bool_0;

		private readonly string string_0;

		private readonly FileSystemWatcher fileSystemWatcher_0 = new FileSystemWatcher();

		[CompilerGenerated]
		private List<T> list_0;

		[CompilerGenerated]
		private EventHandler eventHandler_0;

		public List<T> Instances
		{
			[CompilerGenerated]
			get
			{
				return list_0;
			}
			[CompilerGenerated]
			private set
			{
				list_0 = value;
			}
		}

		public event EventHandler Reloaded
		{
			[CompilerGenerated]
			add
			{
				EventHandler eventHandler = eventHandler_0;
				EventHandler eventHandler2;
				do
				{
					eventHandler2 = eventHandler;
					EventHandler value2 = (EventHandler)Delegate.Combine(eventHandler2, value);
					eventHandler = Interlocked.CompareExchange(ref eventHandler_0, value2, eventHandler2);
				}
				while ((object)eventHandler != eventHandler2);
			}
			[CompilerGenerated]
			remove
			{
				EventHandler eventHandler = eventHandler_0;
				EventHandler eventHandler2;
				do
				{
					eventHandler2 = eventHandler;
					EventHandler value2 = (EventHandler)Delegate.Remove(eventHandler2, value);
					eventHandler = Interlocked.CompareExchange(ref eventHandler_0, value2, eventHandler2);
				}
				while ((object)eventHandler != eventHandler2);
			}
		}

		public AssemblyLoader(string directory, bool detectFileChanges)
		{
			Instances = new List<T>();
			string_0 = directory;
			bool_0 = detectFileChanges;
			if (bool_0)
			{
				fileSystemWatcher_0.Path = directory;
				fileSystemWatcher_0.Filter = "*.cs";
				fileSystemWatcher_0.IncludeSubdirectories = true;
				fileSystemWatcher_0.EnableRaisingEvents = true;
				fileSystemWatcher_0.Changed += delegate(object sender, FileSystemEventArgs e)
				{
					Reload(e.ChangeType.ToString());
				};
				fileSystemWatcher_0.Created += delegate(object sender, FileSystemEventArgs e)
				{
					Reload(e.ChangeType.ToString());
				};
				fileSystemWatcher_0.Deleted += delegate(object sender, FileSystemEventArgs e)
				{
					Reload(e.ChangeType.ToString());
				};
			}
			Reload("Initializing");
		}

		public void Reload(string reason)
		{
			ilog_0.Debug($"Reloading AssemblyLoader<{typeof(T)}> - {reason}");
			Instances = new List<T>();
			if (!Directory.Exists(string_0))
			{
				ilog_0.Error($"Could not Reload assemblies because the path \"{string_0}\" does not exist.");
				return;
			}
			string[] directories = Directory.GetDirectories(string_0);
			foreach (string path in directories)
			{
				try
				{
					CodeCompiler codeCompiler = new CodeCompiler(path);
					CompilerResults compilerResults = codeCompiler.Compile();
					if (compilerResults == null)
					{
						continue;
					}
					if (compilerResults.Errors.HasErrors)
					{
						foreach (object error in compilerResults.Errors)
						{
							ilog_0.Error("Compiler Error: " + error.ToString());
						}
					}
					else
					{
						Instances.AddRange(new TypeLoader<T>(codeCompiler.CompiledAssembly));
					}
				}
				catch (Exception ex)
				{
					if (ex is ReflectionTypeLoadException)
					{
						Exception[] loaderExceptions = (ex as ReflectionTypeLoadException).LoaderExceptions;
						foreach (Exception exception in loaderExceptions)
						{
							ilog_0.Error("[Reload] An exception occurred.", exception);
						}
					}
					else
					{
						ilog_0.Error("[Reload] An exception occurred.", ex);
					}
				}
			}
			foreach (T gparam_2 in new TypeLoader<T>())
			{
				if (!Instances.Any(delegate(T gparam_1)
				{
					string fullName = gparam_1.GetType().FullName;
					string fullName2 = gparam_2.GetType().FullName;
					return fullName == fullName2;
				}))
				{
					Instances.Add(gparam_2);
				}
			}
			if (eventHandler_0 != null)
			{
				eventHandler_0(this, null);
			}
		}

		[CompilerGenerated]
		private void method_0(object sender, FileSystemEventArgs e)
		{
			Reload(e.ChangeType.ToString());
		}

		[CompilerGenerated]
		private void method_1(object sender, FileSystemEventArgs e)
		{
			Reload(e.ChangeType.ToString());
		}

		[CompilerGenerated]
		private void method_2(object sender, FileSystemEventArgs e)
		{
			Reload(e.ChangeType.ToString());
		}
	}
}
